package com.hzw.saas.common.storage.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.hzw.saas.common.util.PathUtils;
import com.hzw.saas.common.util.SnowFlakeUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 文件存储Key工具类
 *
 * @author zzl
 * @since 10/20/2021
 */
@Slf4j
public final class StorageKeyUtil {

    /**
     * 生成文件Key
     *
     * @return key
     */
    public static long generateKey() {
        return SnowFlakeUtil.nextId();
    }

    /**
     * 生成文件Key
     *
     * @return key
     */
    public static String generateKeyStr() {
        return SnowFlakeUtil.nextIdStr();
    }

    /**
     * 根据文件根目录和key获取文件路径
     *
     * @param fileRoot 根目录
     * @param fileKey key
     * @return 文件全路径
     */
    public static String getFilePath(String fileRoot, Long fileKey) {
        return PathUtils.connectPath(fileRoot, getFileSupPath(fileKey), String.valueOf(fileKey));
    }

    /**
     * 根据文件根目录和key获取文件路径
     *
     * @param fileRoot 根目录
     * @param fileKey key
     * @return 文件全路径
     */
    public static String getFilePath(String fileRoot, String fileKey) {
        return PathUtils.connectPath(fileRoot, getFileSupPath(fileKey), fileKey);
    }

    /**
     * 根据文件根目录和key获取文件上级目录路径
     *
     * @param fileRoot 根目录
     * @param fileKey key
     * @return 文件上级目录路径
     */
    public static String getFileSupPath(String fileRoot, Long fileKey) {
        return PathUtils.connectPath(fileRoot, getFileSupPath(fileKey));
    }

    /**
     * 根据文件根目录和key获取文件上级目录路径
     *
     * @param fileRoot 根目录
     * @param fileKey key
     * @return 文件上级目录路径
     */
    public static String getFileSupPath(String fileRoot, String fileKey) {
        return PathUtils.connectPath(fileRoot, getFileSupPath(fileKey));
    }

    /**
     * 根据缓存根目录和文件key获取文件缓存目录路径
     *
     * @param cacheRoot 缓存根目录
     * @param fileKey key
     * @return 文件缓存目录路径
     */
    public static String getCacheSupPath(String cacheRoot, Long fileKey) {
        return PathUtils.connectPath(cacheRoot, getCacheSupPath(fileKey));
    }

    /**
     * 根据缓存根目录和文件key获取文件缓存目录路径
     *
     * @param cacheRoot 缓存根目录
     * @param fileKey key
     * @return 文件缓存目录路径
     */
    public static String getCacheSupPath(String cacheRoot, String fileKey) {
        return PathUtils.connectPath(cacheRoot, getCacheSupPath(fileKey));
    }

    public static String getThumbnailKey(String imgKey, long size) {
        Assert.notBlank(imgKey, "image key is blank");
        return imgKey.concat("_").concat(String.valueOf(size));
    }

    // ================================================ private method ================================================ //

    /**
     * 获取文件所在目录路径
     * 该目录可以根据key推算获得
     *
     * @param fileKey key
     * @return 文件所在目录(相对存储根目录)
     */
    private static String getFileSupPath(Long fileKey) {
        Assert.notNull(fileKey, "key is null");
        long time = SnowFlakeUtil.instance.getGenerateDateTime(fileKey);
        return DateUtil.date(time).toDateStr();
    }

    /**
     * 获取文件所在目录路径
     * 该目录可以根据key推算获得
     *
     * @param fileKey key
     * @return 文件所在目录(相对存储根目录)
     */
    private static String getFileSupPath(String fileKey) {
        Assert.isTrue(StrUtil.isNotBlank(fileKey), "key is blank");
        try {
            long key = Long.parseLong(fileKey);
            return getFileSupPath(key);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("key is invalid");
        }
    }

    /**
     * 获取文件缓存目录路径
     * 该目录可以根据key推算获得
     *
     * @param fileKey key
     * @return 文件缓存目录(相对缓存根目录)
     */
    private static String getCacheSupPath(Long fileKey) {
        Assert.notNull(fileKey, "key is null");
        return String.valueOf(fileKey);
    }

    /**
     * 获取文件缓存目录路径
     * 该目录可以根据key推算获得
     *
     * @param fileKey key
     * @return 文件缓存目录(相对缓存根目录)
     */
    private static String getCacheSupPath(String fileKey) {
        Assert.isTrue(StrUtil.isNotBlank(fileKey), "key is blank");
        return fileKey;
    }

    private StorageKeyUtil() {
        throw new UnsupportedOperationException("Private constructor, cannot be accessed.");
    }
}
